package cn.edu.zjicm.wordsnet_d.data.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import android.content.Context;
import android.widget.Toast;
import cn.edu.zjicm.wordsnet_d.activity.ExamConsolidateActivity;
import cn.edu.zjicm.wordsnet_d.activity.ExamReviewActivity;
import cn.edu.zjicm.wordsnet_d.data.DataManager;
import cn.edu.zjicm.wordsnet_d.data.OneWord;
import cn.edu.zjicm.wordsnet_d.data.StaticData;
import cn.edu.zjicm.wordsnet_d.db.WordFactory;
import cn.edu.zjicm.wordsnet_d.util.DateTimeUtils;
import cn.edu.zjicm.wordsnet_d.util.LogUtil;

public class ConsolidateManager {
	private List<Question> allQuestionList = new LinkedList<Question>();
	private List<Question> vagueWordsList = new LinkedList<Question>();
	private Context mContext;
	private WordFactory wf;
	private int cosolidateNumsLatestToday;
	private int cosolidateNumsLatestIn3Days;
	private int cosolidateNumsLatestIn7Days;
	private int cosolidateNumsLatestAfter7Days;
	// private final int handlerUpdateResult = 1;
	private int currentIndex = 0;

	public boolean hasWordsToConsolidate;

	// Handler mHandler = new Handler(new Callback() {
	// @Override
	// public boolean handleMessage(Message msg) {
	// switch (msg.what) {
	// case handlerUpdateResult:
	// ((ExamConsolidateActivity) mContext).updateResult();// 刷新进度条数据
	// ((ExamConsolidateActivity) mContext).currentQuestionUrgency =
	// getCurrentQuestionUrgency(getCurrentIndex());
	// break;
	// }
	// return false;
	// }
	// });

	public static enum QUESTION_URGENCY {
		TODAY, IN_3_DAYS, IN_7_DAYS, AFTER_7_DAYS
	}

	public ConsolidateManager(Context mContext) {
		this.mContext = mContext;
		wf = WordFactory.getInstance(mContext);
		getAllQuestions();
	}

	private void getAllQuestions() {
		cosolidateNumsLatestToday = wf.getConsolidateNumsLatestToday();
		cosolidateNumsLatestIn3Days = wf.getConsolidateNumsLatestIn3Days();
		cosolidateNumsLatestIn7Days = wf.getConsolidateNumsLatestIn7Days();
		cosolidateNumsLatestAfter7Days = wf.getConsolidateNumsLatestAfter7Days();

		List<OneWord> list = wf.getConsolidateWordsLimitTen();
		LogUtil.e("list1=" + list.size());
		list = shuffleList(list, 0);
		for (int i = 0; i < list.size(); i++) {
			OneWord r = list.get(i);
			allQuestionList.add(new Question(r, mContext));
		}
		hasWordsToConsolidate = true;
		if (list.size() <= 0) {
			hasWordsToConsolidate = false;
		} else {
			if (list.size() >= 10) {
				loadMoreWords();
			}
		}
	}

	private List<OneWord> shuffleList(final List<OneWord> list, int fromIndex) {
		int toIndex = fromIndex + list.size();
		List<OneWord> allList = new ArrayList<OneWord>();
		List<OneWord> todayList = null, in3DaysList = null, in7DaysList = null, after7DaysList = null;
		int numsToday, numsIn3Days, numsIn7Days, numsAfter7Days;

		if (fromIndex < getCosolidateNumsLatestToday()) {
			if (toIndex < getCosolidateNumsLatestToday()) {
				numsToday = list.size();
				numsIn3Days = 0;
				numsIn7Days = 0;
				numsAfter7Days = 0;

				todayList = getSubList(list, 0, numsToday);

			} else if (toIndex < getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days()) {
				numsToday = getCosolidateNumsLatestToday() - fromIndex;
				numsIn3Days = toIndex - getCosolidateNumsLatestToday();
				numsIn7Days = 0;
				numsAfter7Days = 0;

				todayList = getSubList(list, 0, numsToday);
				in3DaysList = getSubList(list, numsToday, numsIn3Days + numsToday);

			} else if (toIndex < getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days() + getCosolidateNumsLatestIn7Days()) {
				numsToday = getCosolidateNumsLatestToday() - fromIndex;
				numsIn3Days = getCosolidateNumsLatestIn3Days();
				numsIn7Days = toIndex - getCosolidateNumsLatestToday() - getCosolidateNumsLatestIn3Days();
				numsAfter7Days = 0;

				todayList = getSubList(list, 0, numsToday);
				in3DaysList = getSubList(list, numsToday, numsIn3Days + numsToday);
				in7DaysList = getSubList(list, numsIn3Days + numsToday, numsIn7Days + numsIn3Days + numsToday);
			} else {
				numsToday = getCosolidateNumsLatestToday() - fromIndex;
				numsIn3Days = getCosolidateNumsLatestIn3Days();
				numsIn7Days = getCosolidateNumsLatestIn7Days();
				numsAfter7Days = toIndex - getCosolidateNumsLatestToday() - getCosolidateNumsLatestIn3Days() - getCosolidateNumsLatestIn7Days();

				todayList = getSubList(list, 0, numsToday);
				in3DaysList = getSubList(list, numsToday, numsIn3Days + numsToday);
				in7DaysList = getSubList(list, numsIn3Days + numsToday, numsIn7Days + numsIn3Days + numsToday);
				after7DaysList = getSubList(list, numsIn7Days + numsIn3Days + numsToday, numsAfter7Days + numsIn3Days + numsToday + numsIn7Days);
			}
		} else if (fromIndex < getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days()) {
			if (toIndex < getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days()) {
				numsToday = 0;
				numsIn3Days = list.size();
				numsIn7Days = 0;
				numsAfter7Days = 0;

				in3DaysList = getSubList(list, 0, numsIn3Days);

			} else if (toIndex < getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days() + getCosolidateNumsLatestIn7Days()) {
				numsToday = 0;
				numsIn3Days = getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days() - fromIndex;
				numsIn7Days = toIndex - getCosolidateNumsLatestToday() - getCosolidateNumsLatestIn3Days();
				numsAfter7Days = 0;

				in3DaysList = getSubList(list, 0, numsIn3Days);
				in7DaysList = getSubList(list, numsIn3Days, numsIn7Days + numsIn3Days);
			} else {
				numsToday = 0;
				numsIn3Days = getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days() - fromIndex;
				numsIn7Days = getCosolidateNumsLatestIn7Days();
				numsAfter7Days = toIndex - getCosolidateNumsLatestToday() - getCosolidateNumsLatestIn3Days() - getCosolidateNumsLatestIn7Days();

				in3DaysList = getSubList(list, 0, numsIn3Days);
				in7DaysList = getSubList(list, numsIn3Days, numsIn7Days + numsIn3Days);
				after7DaysList = getSubList(list, numsIn7Days + numsIn3Days, numsAfter7Days + numsIn3Days + numsIn7Days);
			}
		} else if (fromIndex < getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days() + getCosolidateNumsLatestIn7Days()) {
			if (toIndex < getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days() + getCosolidateNumsLatestIn7Days()) {
				numsToday = 0;
				numsIn3Days = 0;
				numsIn7Days = list.size();
				numsAfter7Days = 0;

				in7DaysList = getSubList(list, 0, numsIn7Days);
			} else {
				numsToday = 0;
				numsIn3Days = 0;
				numsIn7Days = getCosolidateNumsLatestToday() + getCosolidateNumsLatestIn3Days() + getCosolidateNumsLatestIn7Days() - fromIndex;
				numsAfter7Days = toIndex - getCosolidateNumsLatestToday() - getCosolidateNumsLatestIn3Days() - getCosolidateNumsLatestIn7Days();

				in7DaysList = getSubList(list, 0, numsIn7Days);
				after7DaysList = getSubList(list, numsIn7Days, numsAfter7Days + numsIn7Days);
			}
		} else {
			numsToday = 0;
			numsIn3Days = 0;
			numsIn7Days = 0;
			numsAfter7Days = list.size();

			after7DaysList = getSubList(list, 0, numsAfter7Days);
		}

		if (null != todayList) {
			Collections.shuffle(todayList);
			allList.addAll(todayList);
		}
		if (null != in3DaysList) {
			Collections.shuffle(in3DaysList);
			allList.addAll(in3DaysList);
		}
		if (null != in7DaysList) {
			Collections.shuffle(in7DaysList);
			allList.addAll(in7DaysList);
		}
		if (null != after7DaysList) {
			Collections.shuffle(after7DaysList);
			allList.addAll(after7DaysList);
		}
		return allList;
	}

	private List<OneWord> getSubList(final List<OneWord> list, int fromIndex, int toIndex) {
		List sub = list.subList(fromIndex, toIndex);
		List returnList = new ArrayList<OneWord>(sub);
		// sub.clear();
		return returnList;
	}

	public Question nextQuestion() {
		if (allQuestionList.size() < 3) {
			loadMoreWords();
		}
		if (allQuestionList.size() > 0)
			tempFuncationForTest(allQuestionList.get(0).getWord());
		((ExamConsolidateActivity) mContext).updateResult();// 刷新进度条数据
		if (allQuestionList.size() > 0) {
			return allQuestionList.get(0);
		} else
			return null;

	}

	private void judgeSetToTooEasy(Question rQuestion, int tLast, int tNext) {
		OneWord word = rQuestion.getWord();
		int timeSet = word.getTime_set();
		int Cr = word.getConsolidateTestCount();
		int Dn = DateTimeUtils.getDaysBeforeToday(timeSet + "");
		if (((-1.0 * 7 / 30.0 * Dn + 24) <= Cr) && Cr >= 3 && (tNext - tLast > 30)) {
			setWordToTooEasy1100(rQuestion);
		}
	}

	// 点击了“下一个”
	public void rightAnswerBtn(Question rQuestion) {
		if (removeFromVagueWordsList(rQuestion)) {
			if (allQuestionList.size() > 0) {
				allQuestionList.remove(0);
				currentIndex++;
			}
			return;
		}
		int tNow = DateTimeUtils.getDateWithZoneRawOffset();// 现在的时间
		int tNext = rQuestion.getWord().getConsolidateNextTime() / DateTimeUtils.MINUTES_OF_DAY;// 数据库中下次需要记忆的时间
		int tLast = rQuestion.getWord().getLast_test_time() / DateTimeUtils.MINUTES_OF_DAY;// 数据库中上次记忆的时间
		int Tn2;// 下次需要记忆的时间
		if (tNow <= tNext) {
			Tn2 = (tNow - tLast) * 2 + tNext;
		} else {
			int tinTv = (tNext - tLast) * 2 - ((tNow - tNext) / 2);
			if (tinTv >= 7) {
				Tn2 = tNow + tinTv;
			} else {
				Tn2 = tNow + 7;
			}
		}
		OneWord word = rQuestion.getWord();
		word.setConsolidateTestCount(word.getConsolidateTestCount() + 1);
		wf.updateConsolidateTestCounts(word);// 更新数据库中的学习次数
		word.setConsolidateNextTime(Tn2 * DateTimeUtils.MINUTES_OF_DAY);
		wf.updateConsolidateNextTime(word);// 更新数据库中本次的学习时间
		wf.updateCurrentWordTestTime(word);
		judgeSetToTooEasy(rQuestion, tLast, Tn2);
		if (allQuestionList.size() > 0) {
			allQuestionList.remove(0);
			currentIndex++;
		}
		((ExamConsolidateActivity) mContext).updateResult();
		tempFuncationForTest(rQuestion.getWord());
	}

	// 设置为生词
	public void wrongAnswerBtn(Question rQuestion) {
		if (allQuestionList.size() > 0) {
			updataProgressBarWhenRemoveItemFromAllQuestionList(getCurrentIndex());
			allQuestionList.remove(0);
		}
		setWordToUnFamiliar(rQuestion);
		((ExamConsolidateActivity) mContext).updateResult();
		tempFuncationForTest(rQuestion.getWord());
	}

	// 用户选择错误，插入到用户的接下来的复习列表中
	public void wrongAnswerAndTestAgainBtn(Question rQuestion) {
		if (allQuestionList.size() > 0) {
			int currentIndexLeftWords = getCurrentIndexLeftWords();
			if (currentIndexLeftWords >= 10) {
				allQuestionList.add(Math.min(allQuestionList.size(), 10), rQuestion);
			} else {
				allQuestionList.add(Math.min(currentIndexLeftWords, allQuestionList.size()), rQuestion);
			}
			allQuestionList.remove(0);
		}
		((ExamConsolidateActivity) mContext).updateResult();
		if (isInVagueWordsList(rQuestion)) {
			return;
		} else {
			insertIntoVagueWordsList(rQuestion);
			OneWord word = rQuestion.getWord();
			word.setConsolidateTestCount(word.getConsolidateTestCount() + 1);
			wf.updateConsolidateTestCounts(word);// 更新数据库中的学习次数
			int tNow = DateTimeUtils.getDateWithZoneRawOffset();// 现在的时间
			word.setConsolidateNextTime((tNow + 7) * DateTimeUtils.MINUTES_OF_DAY);
			wf.updateConsolidateNextTime(word);// 更新数据库中本次的学习时间
			wf.updateCurrentWordTestTime(word);
		}
		tempFuncationForTest(rQuestion.getWord());
	}

	public void tooEasyBtn(Question rQuestion) {
		if (allQuestionList.size() > 0) {
			setWordToTooEasyNormal(rQuestion);
			allQuestionList.remove(0);
			currentIndex++;
		}
		((ExamReviewActivity) mContext).updateResult();
	}

	private void updataProgressBarWhenRemoveItemFromAllQuestionList(int removeItemIndex) {
		switch (getCurrentQuestionUrgency(removeItemIndex)) {
		case TODAY:
			cosolidateNumsLatestToday--;
			break;
		case IN_3_DAYS:
			cosolidateNumsLatestIn3Days--;
			break;
		case IN_7_DAYS:
			cosolidateNumsLatestIn7Days--;
			break;
		case AFTER_7_DAYS:
			cosolidateNumsLatestAfter7Days--;
			break;
		}
	}

	public int getCurrentIndexLeftWords() {
		int wordsLeftNums = 0;
		switch (getCurrentQuestionUrgency(getCurrentIndex())) {
		case TODAY:
			wordsLeftNums = cosolidateNumsLatestToday - getCurrentIndex();
			break;
		case IN_3_DAYS:
			wordsLeftNums = cosolidateNumsLatestToday + cosolidateNumsLatestIn3Days - getCurrentIndex();
			break;
		case IN_7_DAYS:
			wordsLeftNums = cosolidateNumsLatestToday + cosolidateNumsLatestIn3Days + cosolidateNumsLatestIn7Days - getCurrentIndex();
			break;
		case AFTER_7_DAYS:
			wordsLeftNums = cosolidateNumsLatestToday + cosolidateNumsLatestIn3Days + cosolidateNumsLatestIn7Days + cosolidateNumsLatestAfter7Days - getCurrentIndex();
			break;
		}
		return wordsLeftNums;
	}

	// 设置为太简单，熟悉度为1000
	public void setWordToTooEasyNormal(Question rQuestion) {
		OneWord word = DataManager.getInstance().findWord(rQuestion.getWord(), mContext);
		if (word != null) {
			DataManager.getInstance().changeFamiliarToTooEasy(word, mContext);
			Toast.makeText(mContext, rQuestion.getLemma() + "已设为太简单", Toast.LENGTH_SHORT).show();
		}
	}

	// 设置为太简单，熟悉度为1100
	public void setWordToTooEasy1100(Question rQuestion) {
		OneWord word = DataManager.getInstance().findWord(rQuestion.getWord(), mContext);
		if (word != null) {
			DataManager.getInstance().changeFamiliarToTooEasyForConsolidate(word, mContext);
			Toast.makeText(mContext, rQuestion.getLemma() + "已设为太简单", Toast.LENGTH_SHORT).show();
		}
	}

	// 设置为生词
	public void setWordToUnFamiliar(Question rQuestion) {
		OneWord word = DataManager.getInstance().findWord(rQuestion.getWord(), mContext);
		if (word != null) {
			DataManager.getInstance().changeFamiliarToUnFamiliar(word, mContext);
			Toast.makeText(mContext, rQuestion.getLemma() + "已降级为生词", Toast.LENGTH_SHORT).show();
		}
	}

	public int getCurrentIndex() {
		return currentIndex;
	}

	public QUESTION_URGENCY getCurrentQuestionUrgency(int currentIndex) {
		if (currentIndex < cosolidateNumsLatestToday) {
			return QUESTION_URGENCY.TODAY;
		} else if (currentIndex < (cosolidateNumsLatestToday + cosolidateNumsLatestIn3Days)) {
			return QUESTION_URGENCY.IN_3_DAYS;
		} else if (currentIndex < (cosolidateNumsLatestToday + cosolidateNumsLatestIn3Days + cosolidateNumsLatestIn7Days)) {
			return QUESTION_URGENCY.IN_7_DAYS;
		} else {
			return QUESTION_URGENCY.AFTER_7_DAYS;
		}
	}

	public int getCosolidateNumsLatestToday() {
		return cosolidateNumsLatestToday;
	}

	public int getCosolidateNumsLatestIn3Days() {
		return cosolidateNumsLatestIn3Days;
	}

	public int getCosolidateNumsLatestIn7Days() {
		return cosolidateNumsLatestIn7Days;
	}

	public int getCosolidateNumsLatestAfter7Days() {
		return cosolidateNumsLatestAfter7Days;
	}

	Thread loadMoreWordsThread;

	private synchronized void loadMoreWords() {
		if (loadMoreWordsThread != null)
			return;
		loadMoreWordsThread = new Thread() {
			public void run() {
				int fromIndex = allQuestionList.size() + getCurrentIndex();
				List<OneWord> loadedList = wf.getConsolidateWordsLimit(0, StaticData.BufferSize);
				if (null == loadedList || loadedList.size() <= 0) {
					loadMoreWordsThread = null;
					return;
				}
				loadedList = shuffleList(loadedList, fromIndex);
				for (int i = 0; i < loadedList.size(); i++) {
					OneWord r = loadedList.get(i);
					List<Question> copyOfAllQuestionList = new ArrayList<Question>();
					copyOfAllQuestionList.addAll(allQuestionList);
					boolean isToAdd = true;
					for (int j = 0; j < copyOfAllQuestionList.size(); j++) {
						OneWord wordJ = copyOfAllQuestionList.get(j).getWord();
						if (wordJ.getIndex_word_id() == r.getIndex_word_id()) {
							isToAdd = false;
							break;
						}
					}
					if (isToAdd)
						allQuestionList.add(new Question(r, mContext));
				}
				loadMoreWordsThread = null;
			};
		};
		loadMoreWordsThread.start();
	}

	private void insertIntoVagueWordsList(Question rQuestion) {
		vagueWordsList.add(rQuestion);
	}

	private boolean removeFromVagueWordsList(Question rQuestion) {
		boolean contains = isInVagueWordsList(rQuestion);
		if (contains) {
			vagueWordsList.remove(rQuestion);
		}
		return contains;
	}

	private boolean isInVagueWordsList(Question rQuestion) {
		return vagueWordsList.contains(rQuestion);
	}

	String TAG = "cn.edu.zjicm.wordnet_d.test";

	public void tempFuncationForTest(OneWord word) {
		int wordID = word.getIndex_word_id();
		int timeSet = wf.getTempTimeSet(wordID);
		int degreeFm = wf.getTempDegreeFm(wordID);
		int senseDegreeFm = wf.getTempSenseDegreeFm(wordID);
		int lastTime = wf.getTempLastTestTime(wordID);
		int nextTime = wf.getTempTimeNext(wordID);
		int testCount = wf.getTempTestCount(wordID);

		LogUtil.e(TAG, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" + "\n"
		// ---------------------------------------------
				+ "当前单词            = " + word.getLemma() + "\n"
		// ---------------------------------------------
				+ "timeSet             = " + timeSet + "\n"
				// ---------------------------------------------
				+ "熟悉度(正常值是20)  = " + degreeFm + "\n"
				// ---------------------------------------------
				+ "熟悉度2(正常值是60) = " + senseDegreeFm + "\n"
				// ---------------------------------------------
				+ "lastTime            = " + lastTime / 24 / 60 + "\n"
				// ---------------------------------------------
				+ "nextTime            = " + nextTime / 24 / 60 + "\n"
				// ---------------------------------------------
				+ "巩固次数            = " + testCount + "\n"
				// ---------------------------------------------
				+ "现在日期            = " + DateTimeUtils.getDate() + "\n"
				// ---------------------------------------------
				+ "现在日期            = " + DateTimeUtils.getTimeOfMinuteWithZoneRawOffsetTime() / 24 / 60 + "\n"
				// ---------------------------------------------
				+ ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

	}
}